﻿#include "MainApp.h"
#include <QApplication>
#include <QStackedWidget>
#include <QPalette>
#include <QVBoxLayout>
#include <QPixmap>
#include <QScrollArea>
#include <QDir>
#include <QLabel>
#include <QImage>
#include <QImageReader>
#include <QTimer>
#include <QFile>

#include "glog/logging.h"
#include "version.h"
#include "CDBConnector.h"
#include "CabinetManager.h"
#include "COrderManager.h"
#include "CAudioBroadcast.h"
#include "AppModel.h"
#include "HomeWnd.h"
#include "MainWnd.h"
#include "CBackendWnd.h"
#include "AdWnd.h"
#include "ResourceManager.h"
#include "IPlatformProxyInterface.h"
#include "CPlatformProxyFactory.h"
#include "CPaymentManager.h"
#include "IPayplatInterface.h"
#include "IValidatorInterface.h"
#include "CValidatorFactory.h"

#include "custom/CToastBox.h"
#include "custom/inputnew/frminputnew.h"

#define INDEX_ADWND			0
#define INDEX_HOMEWND		1
#define INDEX_MAINWND		2
#define INDEX_BEWND			3
#define INDEX_INFOWND		4

#define DEFAULT_AUDIOPATH	"./cache/audio"
#define DEFAULT_HOMEITL		20 * 1000
#define DEFAULT_INFOITL		120 * 1000

 CMainApp::CMainApp()
    : timer_status_(-1)
    , timer_heartbeat_(-1)
	, res_mgr_(new CResourceManager)
    , container_(nullptr)
    , ad_wnd_(nullptr)
    , home_wnd_(nullptr)
    , main_wnd_(nullptr)
    , backend_wnd_(nullptr)
    , plat_api_(nullptr)
    , validator_api_(nullptr)
{
     init_logger();
}

CMainApp::~CMainApp()
{
	container_->close();
	container_->deleteLater();

	zl::CCabinetManager::Release();
	zl::COrderManager::Release();
    zl::CDBConnector::Release();
	zl::CAudioBroadcast::Release();

    if (plat_api_ != nullptr)
    {
        plat_api_->Uninitialize();
    }

    if (validator_api_ != nullptr)
    {
        validator_api_->Uninitialize();
    }
	
    LOG(INFO) << "Exit Application...";
    LOG(INFO) << "=========================================";
	QApplication::exit(0);
}

int32_t CMainApp::Run()
{
    LOG(INFO) << "Start Application...";
    LOG(INFO) << "=========================================";
	CToastBox::EnableIcon(true);
    CToastBox::EnableMask(true);
	CToastBox::EnableTitle(false);
	CToastBox::SetTimeout(3000);
    CToastBox::SetAlpha(100);

    // 初始化接口类实例
    init_configuration();
    init_database();
    init_cabinet();
    init_platform_proxy();
    init_audio_broadcast();
    init_resources_manager();
    init_cabint_devices();
    init_view();

    // 更新配置信息
    update_app_configuration();

    // 显示主窗口
    container_->showFullScreen();
    container_->move(0, 0);
    set_current_view(INDEX_HOMEWND);
	return 0;
}

void CMainApp::init_view()
{
    container_ = new QStackedWidget;
    ad_wnd_ = new CAdWnd;
    home_wnd_ = new HomeWnd;
    main_wnd_ = new MainWnd;
    backend_wnd_ = new CBackendWnd;

    container_->setFixedSize(480, 800);
    container_->setWindowFlags(container_->windowFlags() | Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);
    container_->addWidget(ad_wnd_);
    container_->addWidget(home_wnd_);
    container_->addWidget(main_wnd_);
    container_->addWidget(backend_wnd_);
    container_->installEventFilter(this);
    container_->setMouseTracking(true);
    container_->setCurrentIndex(INDEX_HOMEWND);

    // init keyboard
#ifdef __arm__
    //3288 wayland have no parent will crash
    frmInputNew::Instance()->setDeskSize(480,800);
    frmInputNew::Instance()->setParent(backend_wnd_);
#endif
    frmInputNew::Instance()->hide();
    frmInputNew::Instance()->setFrmSize(480,220);

	// init
	backend_wnd_->LoadData();
    ad_wnd_->setStyleSheet(ad_wnd_->styleSheet());
    home_wnd_->setStyleSheet(home_wnd_->styleSheet());
    main_wnd_->setStyleSheet(main_wnd_->styleSheet());
    backend_wnd_->setStyleSheet(backend_wnd_->styleSheet());


    // load default ad image
    ad_wnd_->SetFileList({ "./cache/ad/ad1.png", "./cache/ad/ad2.png", "./cache/ad/ad3.png"});
    ad_wnd_->SetInterval(10 * 1000);

    // ad wnd
    connect(ad_wnd_, &CAdWnd::backToHome, this, &CMainApp::event_back_to_home);

	// main widget event
    connect(main_wnd_, &MainWnd::backToHome, [=](){
       if (container_->currentIndex() == INDEX_MAINWND)
       {
           event_back_to_home();
       }
    });

	// home widget event
	connect(home_wnd_, &HomeWnd::depositEvent, this, [&]() {
        main_wnd_->StartDeposit();
		set_current_view(INDEX_MAINWND);
	});
	connect(home_wnd_, &HomeWnd::fetchEvent, this, [&]() {
        main_wnd_->StartFetch();
		set_current_view(INDEX_MAINWND);
    });
	connect(home_wnd_, &HomeWnd::cardLogin, this, &CMainApp::event_verify_manager_card);

	// backend widget event
	connect(backend_wnd_, &CBackendWnd::backToHome, this, [&]() { 
		if (container_->currentIndex() == INDEX_BEWND)
        {
            set_current_view(INDEX_HOMEWND);
		}
    });
	connect(backend_wnd_, &CBackendWnd::exitApp, this, [&]() { exit_application(); });
	connect(backend_wnd_, &CBackendWnd::configChanged, this, &CMainApp::event_config_changed);
}

void CMainApp::init_configuration()
{
    APPMODEL()->ReadConfiguration();
	LOG(INFO) << "load configuration success";
}

void CMainApp::init_logger()
{
//    QDir dir(QApplication::applicationDirPath());
//    dir.mkdir("logs");

//    google::InitGoogleLogging("");
//    google::SetLogDestination(google::GLOG_INFO, "logs/INFO_");
//    google::SetLogDestination(google::GLOG_ERROR, "logs/ERROR_");
//    google::SetLogDestination(google::GLOG_WARNING, "logs/WARNING_");
//    FLAGS_log_dir = "logs";
//    FLAGS_logtostderr = false;
//    FLAGS_colorlogtostderr = false;				// Set log color
//    FLAGS_logbufsecs = 0;						// Set log output speed(s)
//    FLAGS_max_log_size = 10;					// Set max log file size
//    FLAGS_stop_logging_if_full_disk = true;		// If disk is full
}

void CMainApp::init_database()
{
    // default
    zl::CDBConnector::DBConfig db_conf;
    db_conf.type = zl::CDBConnector::EDBType_SQLITE3;
	int32_t ret = zl::CDBConnector::Instance()->Initialize(db_conf);
	if (ret != zl::CDBConnector::EDBError_Success)
	{
		LOG(ERROR) << "init database failed: " << ret;
		return;
	}
}

void CMainApp::init_cabinet()
{
    zl::CCabinetManager::Instance()->InitZLBaseConfig(APPMODEL()->ZLBaseCfg());
    zl::CCabinetManager::Instance()->LoadCabinetData();
    zl::CPaymentManager::Instance()->Initialized();
	connect(zl::CCabinetManager::Instance(), &zl::CCabinetManager::lockerStatusChanged,
		this, &CMainApp::event_cab_locker_status_changed, Qt::QueuedConnection);
}

void CMainApp::init_platform_proxy()
{
    /// 初始化管理台接口
    auto factory = new zl::CPlatformProxyFactory;
    plat_api_ = factory->get();
    zl::IPlatformProxyInterface::PlatConfig conf;
    conf.remote_addr = APPMODEL()->Config().server.remote_addr;
    conf.remote_port = APPMODEL()->Config().server.remote_port;
    conf.local_port = APPMODEL()->Config().server.local_port;
    plat_api_->Initialize(conf, this);

    qRegisterMetaType<zl::PairParams>("zl::PairParams");
    connect(this, &CMainApp::sigPlatReply, this, &CMainApp::event_plat_reply, Qt::QueuedConnection);

    /// 初始化支付服务器接口
    zl::PayplatConfig conf2;
    conf2.auth_id = APPMODEL()->Config().server.auth_id;
    conf2.auth_name = APPMODEL()->Config().server.auth_name;
    conf2.site_id = APPMODEL()->Config().server.site_id;
    conf2.site_name = APPMODEL()->Config().server.site_name;
    conf2.corp_id = APPMODEL()->Config().server.corp_id;
    conf2.corp_name = APPMODEL()->Config().server.corp_name;
    conf2.plat_url = APPMODEL()->Config().server.payplat_uri;
    conf2.timeout = 20;
    zl::GetPayplatInterface()->Initialize(conf2, this);

    // 跟据配置是否开启一码清
     zl::GetPayplatInterface()->EnableOneCode(APPMODEL()->Config().payment.enable_onecode == 1);

    qRegisterMetaType<zl::PayReply>("zl::PayReply");
    connect(this, &CMainApp::sigPayplatReply, this, &CMainApp::event_pay_plat_reply, Qt::QueuedConnection);
}

void CMainApp::init_audio_broadcast()
{
	zl::CAudioBroadcast::Instance()->Init();
	auto ret = zl::CAudioBroadcast::Instance()->LoadMediaResource(DEFAULT_AUDIOPATH);
    LOG(INFO) << "init audio broadcast success";
	if (ret != zl::EResult_Success)
	{
		LOG(ERROR) << "load audio broadcast failed: " << ret << " path:" << DEFAULT_AUDIOPATH;
	}
    LOG(INFO) << "init audio broadcast success";
}

void CMainApp::init_resources_manager()
{
	res_mgr_->setParent(this);

	// connect
	connect(res_mgr_, &CResourceManager::resourceDownloadFinished,
		this, &CMainApp::event_resource_load_finished);
	connect(res_mgr_, &CResourceManager::resourceDownloadProgress,
		this, &CMainApp::event_resource_load_progress);
	connect(res_mgr_, &CResourceManager::installFinished,
		this, &CMainApp::event_install_finished);
}

void CMainApp::init_cabint_devices()
{
    // 当纸币器串口号为0时，默认为没有纸币设备
    if (APPMODEL()->CabinetInfo().validator_com.empty())
    {
        LOG(INFO) << "no default validator device";
        return;
    }

    // 创建纸币器实例
    auto factory = new zl::CValidatorFactory();
    validator_api_ = factory->getValidator(APPMODEL()->CabinetInfo().validator_type);
    if (validator_api_ == nullptr)
    {
        LOG(ERROR) << "create validator instance failed: " << 1;
        return;
    }

    // 打开纸币器
    auto ret = validator_api_->Initialize(APPMODEL()->CabinetInfo().validator_com,
        APPMODEL()->CabinetInfo().validator_baud, this);
    if (ret != zl::EResult_Success)
    {
        LOG(ERROR) << "init itl validator failed: " << ret;
        return;
    }

    // 重置纸币器
    ret = validator_api_->Reset();
    if (ret != zl::EResult_Success)
    {
        LOG(ERROR) << "reset validator failed: " << ret;
        return;
    }

    // 设置纸币器
    ret = validator_api_->Setup();
    if (ret != zl::EResult_Success)
    {
        LOG(ERROR) << "get itl validator information failed: " << ret;
        return;
    }

    connect(this, &CMainApp::sigITLEventCredit, this, &CMainApp::event_itl_event_credit, Qt::QueuedConnection);
    LOG(INFO) << "init itl validator success";
}

void CMainApp::update_app_configuration()
{
	// update api configuration
    zl::COrderManager::Instance()->Init(APPMODEL()->CabinetInfo());

    /// 更新界面显示的信息
    home_wnd_->SetCabinetName(APPMODEL()->CabinetInfo().name.c_str());
    home_wnd_->SetVersion(APP_VERSION);
    main_wnd_->SetViewTimeout(APPMODEL()->Timeout());
    backend_wnd_->UpdatePanelAdvance();

    /// 初始化定时器信息
    if (timer_status_ != -1)
    {
        killTimer(timer_status_);
        timer_status_ = -1;
    }
    if (timer_heartbeat_ != -1)
    {
        killTimer(timer_heartbeat_);
        timer_heartbeat_ = -1;
    }

    auto itl1 = APPMODEL()->Timeout().status_itl;
    auto itl2 = APPMODEL()->Timeout().heartbeat_itl;
    auto itl3 = itl1 > 5 ? itl1 : 5;
    auto itl4 = itl2 > 5 ? itl2 : 5;
    timer_status_ = startTimer(itl3 * 1000);
    timer_heartbeat_ = startTimer(itl4 * 1000);
}

void CMainApp::set_current_view(int index)
{
	container_->setCurrentIndex(index);
    if (!ad_wnd_->Active())
    {
        return;
    }

	if (index == INDEX_HOMEWND)
	{
		static bool flag = false;
		if (flag) return;
		flag = true;

		QTimer::singleShot(DEFAULT_HOMEITL, this, [&]() {
			if (container_->currentIndex() == INDEX_HOMEWND)
			{
				set_current_view(INDEX_ADWND);
            }
            flag = false;
        });
    }
	else if (index == INDEX_INFOWND)
	{
		static bool flag2 = false;
		if (flag2) return;
		flag2 = true;
		QTimer::singleShot(5 * 60 * 1000, this, [&]() {
			if (container_->currentIndex() == INDEX_INFOWND)
			{
				set_current_view(INDEX_ADWND);
			}
			flag2 = false;
		});
	}
	
}

void CMainApp::load_label_pixmap(QLabel * lb, const QString & filename)
{
	QFile file(filename);
	if (!file.open(QIODevice::ReadOnly))
	{
		LOG(ERROR) << "open image file failed " << filename.toStdString();
		return;
	}

	QPixmap pix;
	if (!pix.loadFromData(file.readAll()))
	{
		file.close();
		LOG(ERROR) << "load image data failed " << filename.toStdString();
		return;
	}
	file.close();
	lb->clear();
	lb->setPixmap(pix);
}

void CMainApp::exit_application()
{
	QApplication::exit(0);
}

void CMainApp::auto_upload_unconfirmed()
{
    int send_counter = 0;
    // 获取所有未确认的支付记录信息
    std::vector<zl::PaidDetail> paiddetails;
    zl::CPaymentManager::Instance()->RetrieveAllUnconfirmedPaidDetails(paiddetails);
    for(size_t i = 0; i < paiddetails.size(); i++)
    {
        plat_api_->ReportPaidDetails(CabinetID(), paiddetails.at(i));
        send_counter += 1;
        if(send_counter >= 10)
        {
            return ;
        }
    }

    // 获取所有未确认的订单信息
    zl::OrderVec orders;
    zl::COrderManager::Instance()->GetAllUnconfirmedOrders(orders);
    for(size_t i = 0; i < orders.size(); i++)
    {
        plat_api_->ReportOrderStatus(CabinetID(), orders.at(i));
        send_counter += 1;
        if(send_counter >= 10)
        {
            return ;
        }
    }

    zl::OperLogVec logs;
    zl::COperLogManager::Instance()->GetAllUnconfirmedOperLog(logs);
    for(size_t i = 0; i < logs.size(); i++)
    {
        plat_api_->ReportOperationLogs(logs.at(i));
        send_counter += 1;
        if(send_counter >= 10)
        {
            return ;
        }
    }

    // 自动上传格口状态信息
    zl::LockerVec lockers;
    zl::CCabinetManager::Instance()->GetAllLockers(lockers);
    plat_api_->ReportCabinetStatus(CabinetID(), lockers);
}

void CMainApp::auto_upload_unconfirmed_operlog()
{
    zl::OperLogVec logs;
    auto ret = zl::COperLogManager::Instance()->GetAllUnconfirmedOperLog(logs);
    std::for_each(logs.begin(), logs.end(), [&](const zl::OperLog& log) {
        plat_api_->ReportOperationLogs(log);
    });

}

void CMainApp::auto_upload_unconfirmed_orders()
{
	// get all unconfirm orders
	zl::OrderVec orders;
    zl::COrderManager::Instance()->GetAllUnconfirmedOrders(orders);
    std::for_each(orders.begin(), orders.end(), [&](const zl::Order& order) {
        plat_api_->ReportOrderStatus(CabinetID(), order);
    });
}

void CMainApp::auto_upload_unconfirmed_paid_details()
{
    // 获取所有未确认的支付记录信息
    std::vector<zl::PaidDetail> paiddetails;
    auto ret = zl::CPaymentManager::Instance()->RetrieveAllUnconfirmedPaidDetails(paiddetails);
    std::for_each(paiddetails.begin(), paiddetails.end(), [&](const zl::PaidDetail& details) {
        plat_api_->ReportPaidDetails(CabinetID(), details);
    });
}

bool CMainApp::eventFilter(QObject * watched, QEvent * event)
{
	auto et = event->type();
	if (container_ == qobject_cast<QWidget*>(watched))
	{
		if (event->type() == QEvent::Close)
		{
			exit_application();
		}
	}

	return QObject::eventFilter(watched, event);
}

void CMainApp::timerEvent(QTimerEvent * e)
{
	auto id = e->timerId();
    if (id == timer_status_)
    {
        auto_upload_unconfirmed();
	}
    else if (id == timer_heartbeat_)
    {
        // 上传心跳数据
        plat_api_->RequestSynchronizeTime(CabinetID());
	}
	else
	{
		// todo
	}
}

void CMainApp::event_verify_manager_card(QString cardno)
{
	int32_t ret = zl::CCabinetManager::Instance()->VerifyManagerCard(cardno.toStdString());
    if ((ret == -1) || (ret == zl::ECardStatus_Locked))
	{
        CToastBox::Info(container_, "", tr("Invalid Manager Card No."));
		LOG(ERROR) << "invalid manager card no:" << cardno.toStdString();
		return;
	}
    else
    {
        backend_wnd_->SetAccount(cardno.toStdString());
        backend_wnd_->SetLevel(ret);
        zl::OperLog log = zl::COperLogManager::Instance()->CreateOperLog();
        log.cabinet_no = CabinetID().c_str();
        log.box_no = 0;
        log.action = tr("Login Background").toStdString();
        log.type = tr("Administrators").toStdString();
        log.account = cardno.toStdString();
        zl::COperLogManager::Instance()->CommitOperLog(log);
    }

	set_current_view(INDEX_BEWND);
}

void CMainApp::event_back_to_home()
{
	set_current_view(INDEX_HOMEWND);
}

void CMainApp::event_config_changed()
{
	update_app_configuration();
}

void CMainApp::event_cab_locker_status_changed(int32_t locker)
{
	LOG(INFO) << "cabinet locker status changed: " << locker;
	backend_wnd_->UpdateLockerStatus();
}

void CMainApp::event_resource_load_finished(int type, bool flag, QString filename)
{
	LOG(INFO) << "resource download finished: " << type << " " << flag << " " << filename.toStdString();
	if (!flag)
	{
		LOG(ERROR) << "resource download failed";
		return;
	}

	// todo
	switch (type)
	{
	case CResourceManager::EResType_Installer:
		LOG(INFO) << "load installer finished, exec installer";
		res_mgr_->Upgrade(filename);
		break;
    case CResourceManager::EResType_ADWait:
        // ad_wnd_->AppendFile(filename.isEmpty() ? DEFAULT_ADWAIT : filename);
        break;
	default:
		return;
	}
}

void CMainApp::event_resource_load_progress(int type, qint64 cur, qint64 total)
{
	// LOG(INFO) << "resource load progress: " << cur << " " << total;
	// todo
}

void CMainApp::event_install_finished()
{
	LOG(INFO) << "installer install finished";
}

void CMainApp::event_plat_reply(const zl::PairParams &data)
{
    try {
        auto tcode = data.at("tcode");
        // LOG(INFO) << "event manager plat command: " << tcode;
        // 根据管理台回传的数据，确认订单信息
        if (tcode == "1001")
        {
            // 终端上传存包信息回复
            auto order_id = data.at("log_id");
            LOG(INFO) << "reply deposit confirm order:" << order_id;
            zl::COrderManager::Instance()->ConfirmOrder(order_id, 0x01);
        }
        else if (tcode == "1002")
        {
            // 终端上传取包信息回复
            auto order_id = data.at("log_id");
            LOG(INFO) << "reply fetch confirm order:" << order_id;
            zl::COrderManager::Instance()->ConfirmOrder(order_id, 0x02);
        }
        else if (tcode == "1012")
        {
            // 终端查询异柜存包信息回复
            auto cabinet_id = data.at("cabinet_id");
            auto box_id = std::stoi(data.at("box_id"));
            LOG(INFO) << "reply order details:" << box_id << "@" << cabinet_id;
            main_wnd_->EventRequestOrderDetails("", cabinet_id, box_id);
        }
        else if (tcode == "1003")
        {
            // 终端上传扣费报文回复
            auto paid_order_id = data.at("log_id");
            LOG(INFO) << "reply confirm paid details:" << paid_order_id;
            zl::CPaymentManager::Instance()->ConfirmPaidDetails(paid_order_id);
        }
        else if (tcode == "1004")
        {
            // 终端上传柜子状态回复
        }
        else if (tcode == "1007")
        {
            // TODO 终端日志上传回复
            auto log_id = data.at("log_id");
            LOG(INFO) << "reply confirm oper log:" << log_id;
            zl::COperLogManager::Instance()->ConfirmOperLog(log_id);
        }
        else if (tcode == "1011")
        {
            // 终端同步时间请求回复
            // LOG(INFO) << "platform reply synchronize time";
        }
        else if (tcode == "1009")
        {
            // 服务器撤销交易
        }
        else if (tcode == "1005")
        {
            // 服务器远程开箱
            int32_t ret = 0;
            auto box_id = std::stoi(data.at("box_id"));
            LOG(INFO) << "remote open box: " << box_id << " result:" << ret;
            if (box_id == 0)
            {
                ret = zl::CCabinetManager::Instance()->OpenAll();
            }
            else
            {
                ret = zl::CCabinetManager::Instance()->OpenBox(box_id);
            }

            zl::OperLog log = zl::COperLogManager::Instance()->CreateOperLog();
            log.cabinet_no = CabinetID().c_str();
            log.box_no = box_id;
            log.action = tr("Remote Opening").toStdString();
            log.type = tr("Backstage Administrator").toStdString();
            log.account = tr("Backstage Administrator").toStdString();
            zl::COperLogManager::Instance()->CommitOperLog(log);

            std::string log_id = data.at("log_id");
            plat_api_->ResponseOpenBox(log_id, log.cabinet_no, std::to_string(box_id));

        }
        else if (tcode == "1006")
        {
            // 服务器远程清箱
            // 先取消订单信息
            int32_t boxno = std::stoi(data.at("box_id"));
            LOG(INFO) << "remote clean box: " << boxno;

            // 清除流程
            auto pfunc = [](int32_t no) {
                // 查询该格口上的订单信息，如果有则清除订单
                zl::Order order;
                auto ret = zl::COrderManager::Instance()->GetOrderByBoxno(order, no);
                if (ret == zl::EResult_Success)
                {
                    // 清除订单信息
                    ret = zl::COrderManager::Instance()->CancelOrder(order);
                    LOG(INFO) << "remote clean box failed, cancel order: " << order.order_id << " " << ret;
                    if (ret != zl::EResult_Success)
                    {
                        // 清除订单失败
                        return;
                    }
                }
                // 清除格口的占用状态
                ret = zl::CCabinetManager::Instance()->CleanBox(no);
                LOG(INFO) << "remote clean box, clean box status: " << ret;

            };

            if (boxno == 0)
            {
                // 全清
                zl::LockerVec lockers;
                zl::CCabinetManager::Instance()->GetAllLockers(lockers);
                for (auto l : lockers)
                {
                    pfunc(l.boxno);
                }
            }
            else
            {
                // 清除指定
                pfunc(boxno);
            }

            zl::OperLog log = zl::COperLogManager::Instance()->CreateOperLog();
            log.cabinet_no = CabinetID().c_str();
            log.box_no = boxno;
            log.action = tr("Remote Clear Box").toStdString();
            log.type = tr("Backstage Administrator").toStdString();
            log.account = tr("Backstage Administrator").toStdString();
            zl::COperLogManager::Instance()->CommitOperLog(log);

            std::string log_id = data.at("log_id");
            plat_api_->ResponseClearBox(log_id, log.cabinet_no, std::to_string(boxno));
        }
        else if( tcode == "1013")
        {
            // 关机
            std::string log_id = data.at("log_id");
            LOG(INFO) << "reply confirm 1013 oper log:" << log_id;
            std::string opertype = data.at("oper_type");
            LOG(INFO) << "oper_type:" << opertype;
            plat_api_->ResponseClearBox(log_id, CabinetID().c_str(), opertype);
            if(opertype == "1")
            {
                system("shutdown -r -t 00");
            }
            else if(opertype == "2")
            {
                system("shutdown -s -t 00");
            }
        }
    }
    catch(std::exception& e)
    {
        LOG(ERROR) << "plat reply, value not found with key: " << e.what();
    }
    return;
}

void CMainApp::event_pay_plat_reply(zl::PayReply rep, int code)
{
    LOG(INFO) << "pay plat reply:" << rep.type << " code:" << code;
    main_wnd_->EventPayplatReply(rep, code);
}

void CMainApp::event_itl_event_credit(int value, QString currency)
{
    LOG(INFO) << "itl validator event credit: " << value << " @ " << currency.toStdString();
    main_wnd_->EventITLEventCredit(value, currency);
}
